package com.hk.sync.address.controller;

import com.alibaba.fastjson.JSONObject;
import com.hk.sync.address.bean.Node;
import com.hk.sync.address.bean.NodeList;
import com.hk.sync.address.service.USDTService;
import com.hk.sync.address.util.runner.ThreadSafe;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;


@RestController
@Slf4j
public class ApiController {

    private List<String> addressListPool = new ArrayList<String>();//缓存地址池

    @Autowired
    private USDTService usdtService;
    @Autowired
    private NodeList nodeList;
    @Autowired
    private ThreadSafe threadSafe;

    @RequestMapping(value = "/getnewaddress", method = RequestMethod.POST)
    public String generateAddress() {
        Map<String, String> res = new HashMap<String, String>();
        res.put("error", "获取地址失败");
        res.put("result", "");
        try {
            boolean isLocked = threadSafe.getLock().tryLock(1, TimeUnit.SECONDS);
            if(!isLocked){
                log.error("APi REQUEST 尝试加锁失败");
                return JSONObject.toJSONString(res);
            }
            //节点信息获取失败直接返回
            if (nodeList.getNodes().size() < 0) return JSONObject.toJSONString(res);

            List<Integer> addressNumber = new ArrayList<Integer>();
            for (Node node : nodeList.getNodes()) {
                usdtService.setNode(node);
                int sum = usdtService.addressNumberByAccount("");
                log.info("API REQUEST 节点信息: " + node.getUrl() + "  节点地址数量: " + sum);
                addressNumber.add(sum);
            }
            HashSet<Integer> h = new HashSet<Integer>(addressNumber);
            if (h.size() == 1) {//节点中地址相同
                if (addressListPool.size() > 1) {
                    log.error("缓存地址池出错 : " + addressListPool.size());
                    return JSONObject.toJSONString(res);
                } else if (addressListPool.size() == 1) {
                    log.info("缓存地址池中的地址: " + JSONObject.toJSONString(addressListPool));
                    res.put("error", null);
                    res.put("result", addressListPool.get(0));
                    addressListPool.remove(0);
                    return JSONObject.toJSONString(JSONObject.toJSONString(res));
                }

                List<String> addressTempList = new ArrayList<String>();
                for (Node node : nodeList.getNodes()) {
                    usdtService.setNode(node);
                    usdtService.walletPassphrase(2);
                    String address = usdtService.getNewAddress();
                    usdtService.walletLock();
                    if (StringUtils.isEmpty(address)) break;
                    addressTempList.add(address);
                    log.info("接收API请求生成地址: {节点: " + node.getUrl() + "  地址: " + address + "}");
                }
                HashSet<String> tempHashSet = new HashSet<String>(addressTempList);
                if ((addressTempList.size() != nodeList.getNodes().size()) || (tempHashSet.size() != 1)) {
                    log.error("接收API请求 节点生成地址过程中出错 ");
                    log.info("钱包地址加入缓存池: { " + JSONObject.toJSONString(tempHashSet) + " }");
                    if (tempHashSet.size() == 1) addressListPool.addAll(tempHashSet);
                } else {
                    res.put("error", null);
                    res.put("result", addressTempList.get(0));//任意取出一个
                    return JSONObject.toJSONString(res);
                }
            }
        } catch (Exception e) {
            log.error("API请求异常: " + e.getMessage());
        } finally {
            if (threadSafe.getLock().isHeldByCurrentThread()) {
                threadSafe.getLock().unlock();
            }
        }
        return JSONObject.toJSONString(res);
    }
}
